﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading;
using System.Windows.Forms;

namespace debugger
{


    public partial class Form3 : Form
    {
        public Form3()
        {
            InitializeComponent();
        }

        public Form1 mainForm;

        private void Form2_Load(object sender, EventArgs e)
        {
        }

        private void spiCSOn()
        {
            mainForm.sendCmd(Form1.SPIROM_DEBUG_CS1);

        }
        private void spiCSOff()
        {
            mainForm.sendCmd(Form1.SPIROM_DEBUG_CS0);

        }

        private uint spiRec()
        {
            uint temp = mainForm.sendCmdRet(Form1.SPIROM_REC);
            return temp;
        }

        private void spiSend(int val)
        {
            //mainForm.sendCmd(Form1.SPIROM_SETDAT, (uint)val);
            uint temp = mainForm.sendCmdRet(Form1.SPIROM_SND, (uint)val);
            if (temp != 123)
            {
                throw new Exception("checkerror");
            }
        }

        private void spiSend4(int val0, int val1, int val2, int val3)
        {
            uint val = 0;
            val |= (uint)val0 & 0xFF;
            val |= (uint)((val1 & 0xFF) << 8);
            val |= (uint)((val2 & 0xFF) << 16);
            val |= (uint)((val3 & 0xFF) << 24);
            uint temp = mainForm.sendCmdRet(Form1.SPIROM_SND4, val);
            if (temp != 123)
            {
                throw new Exception("checkerror");
            }
        }

        int WaitUntilReady()
        {
            int cnt = 0;
            while (true)
            {
                spiCSOn();
                spiSend(0x05);

                uint val = spiRec();
                spiCSOff();

                if ((val & 1) == 0) { break; }

                cnt++;
            }
            return cnt;
        }
        private uint readByte(int addr)
        {
            spiCSOn();
            spiSend(0x0B);

            spiSend((addr >> 16) & 0x0FF);
            spiSend((addr >> 8) & 0x0FF);
            spiSend((addr >> 0) & 0x0FF);

            spiSend(0x00);

            uint val = spiRec();

            spiCSOff();

            return val;
        }

        private void button1_Click(object sender, EventArgs e)
        {

            spiCSOn();
            spiSend(0x9F);
            textBox1.Text = Util.getHex2(spiRec()) + "," + Util.getHex2(spiRec()) + "," + Util.getHex2(spiRec());
            //ef,40,17 w25q64

            spiCSOff();

        }

        private void button2_Click(object sender, EventArgs e)
        {
            int sector = int.Parse(this.textBox2.Text);

            byte[] data = readSector(sector);

            int err = 0;
            StringBuilder sb = new StringBuilder();
            for (int i = 0; i < 4096; i++)
            {
                if ((i & 15) == 0)
                {
                    sb.Append("\r\n");
                }
                sb.Append(Util.getHex2(data[i]));
                sb.Append(" ");
            }

            textBox1.Text = err + ",\r\n" + sb.ToString();

        }

        private void button3_Click(object sender, EventArgs e)
        {
            int totalM = int.Parse(this.textBox3.Text);

            byte[] buff = new byte[totalM * 1024 * 1024];

            FileStream fs = new FileStream("rom.bin", FileMode.Open, FileAccess.Read);
            fs.Read(buff, 0, totalM * 1024 * 1024);
            fs.Close();

            for (int i = 0; i < 256 * totalM; i++)
            {
                int errcount = 0;
                while (true)
                {
                    try
                    {
                        byte[] data = readSectorMem(i);
                        bool isSame = true;
                        for (int j = 0; j < 4096; j++)
                        {
                            if (buff[i * 4096 + j] != data[j])
                            {
                                isSame = false;
                                break;
                            }
                        }
                        if (!isSame)
                        {
                            Console.WriteLine("write sec:" + i);
                            writeSector(i, buff, i * 4096, true, false);//4k / sec
                            errcount++;
                            if (errcount > 10) {
                                return;
                            }
                        }
                        data = readSectorMem(i);
                        int err = 0;
                        for (int j = 0; j < 4096; j++)
                        {
                            if (buff[i * 4096 + j] != data[j])
                            {
                                err++;
                                Console.WriteLine(Util.getHex8(i * 4096 + j) + ":" + Util.getHex2(buff[i * 4096 + j]) + "," + Util.getHex2(data[j]));
                            }
                        }
                        if (err<3)
                        {
                            break;
                        }
                    }
                    catch (Exception ex)
                    {
                    }
                    this.Text = "err";
                    spiCSOn();
                    spiCSOff();
                }
                this.Text = i + "";
            }
            textBox1.Text = "ok";
        }

        private void button4_Click(object sender, EventArgs e)
        {

            spiCSOn();
            spiSend(0x05);
            uint val = spiRec();
            textBox1.Text = "" + Util.getHex2(val) + " " + Util.getBin8(val);
            spiCSOff();

            spiCSOn();
            spiSend(0x35);
            val = spiRec();
            textBox1.Text += " " + Util.getHex2(val) + " " + Util.getBin8(val);
            spiCSOff();

        }

        private void button5_Click(object sender, EventArgs e)
        {

            spiCSOn();
            spiSend(0x06);//we
            spiCSOff();

        }

        private void button6_Click(object sender, EventArgs e)
        {

            spiCSOn();
            spiSend(0x04);//we off
            spiCSOff();

        }

        private void button7_Click(object sender, EventArgs e)
        {
            int sector = int.Parse(this.textBox2.Text);
            
            byte[] data = readSectorMem(sector);

            int err = 0;
            StringBuilder sb = new StringBuilder();
            for (int i = 0; i < 4096; i++)
            {
                if ((i & 15) == 0)
                {
                    sb.Append("\r\n");
                }
                sb.Append(Util.getHex2(data[i]));
                sb.Append(" ");
            }

            textBox1.Text = err + ",\r\n" + sb.ToString();



            //mainForm.clearBuff();
            //byte[] buff = new byte[57344 * 4];
            //
            //FileStream fs = new FileStream("e:\\Bom Bom (Radio Edit) 2.wav", FileMode.Open, FileAccess.Read);
            //fs.Seek(int.Parse(""), SeekOrigin.Begin);
            //fs.Read(buff, 0, 57344 * 4);
            //fs.Close();
            //
            ////mainForm.clearBuff();
            //for (int i = 0; i < 57344; i++)
            //{
            //    double v = i;
            //    v = v / int.Parse("");
            //    v = Math.Sin(v);
            //    v = v + 1;
            //    v = v * 128;
            //
            //    uint val = buff[i * 4];
            //    val += buff[i * 4 + 1];
            //    val += buff[i * 4 + 2];
            //    val += buff[i * 4 + 3];
            //    val = val / 4;
            //    mainForm.setmem((uint)i, val, true);
            //    if ((i & 1023) == 0) this.Text = i + "";
            //}
        }

        private void writeSector(int sec, byte[] data, int offset, bool spi4, bool fast)
        {
            int addr = sec * 4096;

            while (true)
            {
                spiCSOn();
                spiSend(0x06);//we
                spiCSOff();

                spiCSOn();
                spiSend(0x05);
                uint val = spiRec();
                spiCSOff();
                if ((val & 2) != 2)
                {
                    Console.WriteLine("WEL");
                }
                else {
                    break;
                }
            }

            spiCSOn();
            if (spi4)
            {
                spiSend4(0x20, (addr >> 16) & 0x0FF, (addr >> 8) & 0x0FF, (addr >> 0) & 0x0FF);
            }
            else
            {
                spiSend(0x20);//se
                spiSend((addr >> 16) & 0x0FF);
                spiSend((addr >> 8) & 0x0FF);
                spiSend((addr >> 0) & 0x0FF);
            }
            spiCSOff();

            int cnt = WaitUntilReady();

            //mainForm.sendCmd(Form1.SET_TRANSFER_BASE_ADDR, 0);

            for (int page = 0; page < 16; page++)
            {

                while (true)
                {
                    spiCSOn();
                    spiSend(0x06);//we
                    spiCSOff();

                    spiCSOn();
                    spiSend(0x05);
                    uint val = spiRec();
                    spiCSOff();
                    if ((val & 2) != 2)
                    {
                        Console.WriteLine("WEL");
                    }
                    else
                    {
                        break;
                    }
                }

                spiCSOn();
                addr = sec * 4096 + page * 256;

                if (spi4)
                {
                    spiSend4(0x02, (addr >> 16) & 0x0FF, (addr >> 8) & 0x0FF, (addr >> 0) & 0x0FF);
                }
                else
                {
                    spiSend(0x02);//pp
                    spiSend((addr >> 16) & 0x0FF);
                    spiSend((addr >> 8) & 0x0FF);
                    spiSend((addr >> 0) & 0x0FF);
                }

                if (fast)
                {
                    byte[] buff = new byte[256];//256used
                    for (int i = 0; i < 256; i++)
                    {
                        buff[i] = data[offset + page * 256 + i];
                        //if ((i & 15) == 0)
                        //{
                        //    Console.WriteLine();
                        //}
                        //Console.Write(Util.getHex2(buff[i]) + " ");
                    }
                    mainForm.writeMem(0, buff);//256byte
                    mainForm.sendCmd(Form1.SET_DEBUG_ADDRESS, 0);
                    uint temp = mainForm.sendCmdRet(Form1.SPIROM_TRANS_WRITE);//256byte
                    if (temp != 123)
                    {
                        throw new Exception("checkerror");
                    }
                }
                else
                {
                    if (spi4)
                    {
                        for (int i = 0; i < 256; i += 4)
                        {
                            spiSend4(data[offset + page * 256 + i], data[offset + page * 256 + i + 1], data[offset + page * 256 + i + 2], data[offset + page * 256 + i + 3]);
                        }
                    }
                    else
                    {
                        for (int i = 0; i < 256; i++)
                        {
                            spiSend(data[offset + page * 256 + i]);
                        }
                    }
                }

                this.Text = page + "";

                spiCSOff();
                cnt = WaitUntilReady();
            }

        }

        private void writeSectorByte(int sec, byte[] data, int offset)
        {
            int addr = sec * 4096;

            while (true)
            {
                spiCSOn();
                spiSend(0x06);//we
                spiCSOff();

                spiCSOn();
                spiSend(0x05);
                uint val = spiRec();
                spiCSOff();
                if ((val & 2) != 2)
                {
                    Console.WriteLine("WEL");
                }
                else
                {
                    break;
                }
            }

            spiCSOn();
            spiSend(0x20);//se
            spiSend((addr >> 16) & 0x0FF);
            spiSend((addr >> 8) & 0x0FF);
            spiSend((addr >> 0) & 0x0FF);

            spiCSOff();

            int cnt = WaitUntilReady();

            //mainForm.sendCmd(Form1.SET_TRANSFER_BASE_ADDR, 0);

            for (int page = 0; page < 16; page++)
            {

                addr = sec * 4096 + page * 256;

                for (int i = 0; i < 256; i++)
                {

                    while (true)
                    {
                        spiCSOn();
                        spiSend(0x06);//we
                        spiCSOff();

                        spiCSOn();
                        spiSend(0x05);
                        uint val = spiRec();
                        spiCSOff();
                        if ((val & 2) != 2)
                        {
                            Console.WriteLine("WEL");
                        }
                        else
                        {
                            break;
                        }
                    }

                    spiCSOn();
                    spiSend(0x02);//pp
                    spiSend((addr >> 16) & 0x0FF);
                    spiSend((addr >> 8) & 0x0FF);
                    spiSend((i) & 0x0FF);

                    spiSend(data[offset + page * 256 + i]);

                    spiCSOff();
                    cnt = WaitUntilReady();
                }

                this.Text = page + "";

            }

        }

        //private byte[] readSectorMemOld(int sec)
        //{
        //    spiCSOn();
        //
        //    byte[] data = new byte[4096];
        //    int addr = sec * 4096;
        //    byte[] data_buff = new byte[1024];
        //    mainForm.getmem(0x40000000, null);
        //    for (uint j = 0; j < 4096; j += 1024)
        //    {
        //        mainForm.memBatchRead1024(data_buff, (uint)(0x40000000 + sec * 4096 + j));
        //        for (int i = 0; i < 1024; i++)
        //        {
        //            data[i + j] = data_buff[i];
        //        }
        //    }
        //    spiCSOff();
        //
        //    return data;
        //}

        private byte[] readSectorMem(int sec)
        {
            //spiCSOn();
            int size = Math.Max(mainForm.packageSize, 4096);
            byte[] data = new byte[size];

            mainForm.readMem((uint)(0x40000000 + sec * 4096), data);

            //spiCSOff();

            return data;
        }

        private byte[] readSector(int sec)
        {
            byte[] data = new byte[4096];
            int addr = sec * 4096;
            spiCSOn();
            spiSend(0x0B);
            //spiSend((addr >> 16) & 0x0FF);
            //spiSend((addr >> 8) & 0x0FF);
            //spiSend((addr >> 0) & 0x0FF);
            //spiSend(0x00);
            spiSend4((addr >> 16) & 0x0FF, (addr >> 8) & 0x0FF, (addr >> 0) & 0x0FF, 0x00);

            for (int i = 0; i < 4096; i++)
            {
                data[i] = (byte)spiRec();
            }
            spiCSOff();
            return data;
        }

        uint[] char_table = {
0x00000000,0x00000000,0x00000000,0x00000000, //00
0x00007E81,0xA58181BD,0x9981817E,0x00000000, //01
0x00007EFF,0xDBFFFFC3,0xE7FFFF7E,0x00000000, //02
0x00000000,0x6CFEFEFE,0xFE7C3810,0x00000000, //03
0x00000000,0x10387CFE,0x7C381000,0x00000000, //04
0x00000018,0x3C3CE7E7,0xE718183C,0x00000000, //05
0x00000018,0x3C7EFFFF,0x7E18183C,0x00000000, //06
0x00000000,0x0000183C,0x3C180000,0x00000000, //07
0xFFFFFFFF,0xFFFFE7C3,0xC3E7FFFF,0xFFFFFFFF, //08
0x00000000,0x003C6642,0x42663C00,0x00000000, //09
0xFFFFFFFF,0xFFC399BD,0xBD99C3FF,0xFFFFFFFF, //0A
0x00001E0E,0x1A3278CC,0xCCCCCC78,0x00000000, //0B
0x00003C66,0x6666663C,0x187E1818,0x00000000, //0C
0x00003F33,0x3F303030,0x3070F0E0,0x00000000, //0D
0x00007F63,0x7F636363,0x6367E7E6,0xC0000000, //0E
0x00000018,0x18DB3CE7,0x3CDB1818,0x00000000, //0F
0x0080C0E0,0xF0F8FEF8,0xF0E0C080,0x00000000, //10
0x0002060E,0x1E3EFE3E,0x1E0E0602,0x00000000, //11
0x0000183C,0x7E181818,0x7E3C1800,0x00000000, //12
0x00006666,0x66666666,0x66006666,0x00000000, //13
0x00007FDB,0xDBDB7B1B,0x1B1B1B1B,0x00000000, //14
0x007CC660,0x386CC6C6,0x6C380CC6,0x7C000000, //15
0x00000000,0x00000000,0xFEFEFEFE,0x00000000, //16
0x0000183C,0x7E181818,0x7E3C187E,0x00000000, //17
0x0000183C,0x7E181818,0x18181818,0x00000000, //18
0x00001818,0x18181818,0x187E3C18,0x00000000, //19
0x00000000,0x00180CFE,0x0C180000,0x00000000, //1A
0x00000000,0x003060FE,0x60300000,0x00000000, //1B
0x00000000,0x0000C0C0,0xC0FE0000,0x00000000, //1C
0x00000000,0x00286CFE,0x6C280000,0x00000000, //1D
0x00000000,0x1038387C,0x7CFEFE00,0x00000000, //1E
0x00000000,0xFEFE7C7C,0x38381000,0x00000000, //1F
0x00000000,0x00000000,0x00000000,0x00000000, //20
0x0000183C,0x3C3C1818,0x18001818,0x00000000, //21
0x00666666,0x24000000,0x00000000,0x00000000, //22
0x0000006C,0x6CFE6C6C,0x6CFE6C6C,0x00000000, //23
0x18187CC6,0xC2C07C06,0x0686C67C,0x18180000, //24
0x00000000,0xC2C60C18,0x3060C686,0x00000000, //25
0x0000386C,0x6C3876DC,0xCCCCCC76,0x00000000, //26
0x00303030,0x60000000,0x00000000,0x00000000, //27
0x00000C18,0x30303030,0x3030180C,0x00000000, //28
0x00003018,0x0C0C0C0C,0x0C0C1830,0x00000000, //29
0x00000000,0x00663CFF,0x3C660000,0x00000000, //2A
0x00000000,0x0018187E,0x18180000,0x00000000, //2B
0x00000000,0x00000000,0x00181818,0x30000000, //2C
0x00000000,0x000000FE,0x00000000,0x00000000, //2D
0x00000000,0x00000000,0x00001818,0x00000000, //2E
0x00000000,0x02060C18,0x3060C080,0x00000000, //2F
0x0000386C,0xC6C6D6D6,0xC6C66C38,0x00000000, //30
0x00001838,0x78181818,0x1818187E,0x00000000, //31
0x00007CC6,0x060C1830,0x60C0C6FE,0x00000000, //32
0x00007CC6,0x06063C06,0x0606C67C,0x00000000, //33
0x00000C1C,0x3C6CCCFE,0x0C0C0C1E,0x00000000, //34
0x0000FEC0,0xC0C0FC06,0x0606C67C,0x00000000, //35
0x00003860,0xC0C0FCC6,0xC6C6C67C,0x00000000, //36
0x0000FEC6,0x06060C18,0x30303030,0x00000000, //37
0x00007CC6,0xC6C67CC6,0xC6C6C67C,0x00000000, //38
0x00007CC6,0xC6C67E06,0x06060C78,0x00000000, //39
0x00000000,0x18180000,0x00181800,0x00000000, //3A
0x00000000,0x18180000,0x00181830,0x00000000, //3B
0x00000006,0x0C183060,0x30180C06,0x00000000, //3C
0x00000000,0x007E0000,0x7E000000,0x00000000, //3D
0x00000060,0x30180C06,0x0C183060,0x00000000, //3E
0x00007CC6,0xC60C1818,0x18001818,0x00000000, //3F
0x0000007C,0xC6C6DEDE,0xDEDCC07C,0x00000000, //40
0x00001038,0x6CC6C6FE,0xC6C6C6C6,0x00000000, //41
0x0000FC66,0x66667C66,0x666666FC,0x00000000, //42
0x00003C66,0xC2C0C0C0,0xC0C2663C,0x00000000, //43
0x0000F86C,0x66666666,0x66666CF8,0x00000000, //44
0x0000FE66,0x62687868,0x606266FE,0x00000000, //45
0x0000FE66,0x62687868,0x606060F0,0x00000000, //46
0x00003C66,0xC2C0C0DE,0xC6C6663A,0x00000000, //47
0x0000C6C6,0xC6C6FEC6,0xC6C6C6C6,0x00000000, //48
0x00003C18,0x18181818,0x1818183C,0x00000000, //49
0x00001E0C,0x0C0C0C0C,0xCCCCCC78,0x00000000, //4A
0x0000E666,0x666C7878,0x6C6666E6,0x00000000, //4B
0x0000F060,0x60606060,0x606266FE,0x00000000, //4C
0x0000C6EE,0xFEFED6C6,0xC6C6C6C6,0x00000000, //4D
0x0000C6E6,0xF6FEDECE,0xC6C6C6C6,0x00000000, //4E
0x00007CC6,0xC6C6C6C6,0xC6C6C67C,0x00000000, //4F
0x0000FC66,0x66667C60,0x606060F0,0x00000000, //50
0x00007CC6,0xC6C6C6C6,0xC6D6DE7C,0x0C0E0000, //51
0x0000FC66,0x66667C6C,0x666666E6,0x00000000, //52
0x00007CC6,0xC660380C,0x06C6C67C,0x00000000, //53
0x00007E7E,0x5A181818,0x1818183C,0x00000000, //54
0x0000C6C6,0xC6C6C6C6,0xC6C6C67C,0x00000000, //55
0x0000C6C6,0xC6C6C6C6,0xC66C3810,0x00000000, //56
0x0000C6C6,0xC6C6D6D6,0xD6FEEE6C,0x00000000, //57
0x0000C6C6,0x6C7C3838,0x7C6CC6C6,0x00000000, //58
0x00006666,0x66663C18,0x1818183C,0x00000000, //59
0x0000FEC6,0x860C1830,0x60C2C6FE,0x00000000, //5A
0x00003C30,0x30303030,0x3030303C,0x00000000, //5B
0x00000080,0xC0E07038,0x1C0E0602,0x00000000, //5C
0x00003C0C,0x0C0C0C0C,0x0C0C0C3C,0x00000000, //5D
0x10386CC6,0x00000000,0x00000000,0x00000000, //5E
0x00000000,0x00000000,0x00000000,0x00FF0000, //5F
0x30301800,0x00000000,0x00000000,0x00000000, //60
0x00000000,0x00780C7C,0xCCCCCC76,0x00000000, //61
0x0000E060,0x60786C66,0x6666667C,0x00000000, //62
0x00000000,0x007CC6C0,0xC0C0C67C,0x00000000, //63
0x00001C0C,0x0C3C6CCC,0xCCCCCC76,0x00000000, //64
0x00000000,0x007CC6FE,0xC0C0C67C,0x00000000, //65
0x0000386C,0x6460F060,0x606060F0,0x00000000, //66
0x00000000,0x0076CCCC,0xCCCCCC7C,0x0CCC7800, //67
0x0000E060,0x606C7666,0x666666E6,0x00000000, //68
0x00001818,0x00381818,0x1818183C,0x00000000, //69
0x00000606,0x000E0606,0x06060606,0x66663C00, //6A
0x0000E060,0x60666C78,0x786C66E6,0x00000000, //6B
0x00003818,0x18181818,0x1818183C,0x00000000, //6C
0x00000000,0x00ECFED6,0xD6D6D6C6,0x00000000, //6D
0x00000000,0x00DC6666,0x66666666,0x00000000, //6E
0x00000000,0x007CC6C6,0xC6C6C67C,0x00000000, //6F
0x00000000,0x00DC6666,0x6666667C,0x6060F000, //70
0x00000000,0x0076CCCC,0xCCCCCC7C,0x0C0C1E00, //71
0x00000000,0x00DC7666,0x606060F0,0x00000000, //72
0x00000000,0x007CC660,0x380CC67C,0x00000000, //73
0x00001030,0x30FC3030,0x3030361C,0x00000000, //74
0x00000000,0x00CCCCCC,0xCCCCCC76,0x00000000, //75
0x00000000,0x00666666,0x66663C18,0x00000000, //76
0x00000000,0x00C6C6D6,0xD6D6FE6C,0x00000000, //77
0x00000000,0x00C66C38,0x38386CC6,0x00000000, //78
0x00000000,0x00C6C6C6,0xC6C6C67E,0x060CF800, //79
0x00000000,0x00FECC18,0x3060C6FE,0x00000000, //7A
0x00000E18,0x18187018,0x1818180E,0x00000000, //7B
0x00001818,0x18180018,0x18181818,0x00000000, //7C
0x00007018,0x18180E18,0x18181870,0x00000000, //7D
0x000076DC,0x00000000,0x00000000,0x00000000, //7E
0x00000000,0x10386CC6,0xC6C6FE00,0x00000000, //7F
0x00003C66,0xC2C0C0C0,0xC2663C0C,0x067C0000, //80
0x0000CC00,0x00CCCCCC,0xCCCCCC76,0x00000000, //81
0x000C1830,0x007CC6FE,0xC0C0C67C,0x00000000, //82
0x0010386C,0x00780C7C,0xCCCCCC76,0x00000000, //83
0x0000CC00,0x00780C7C,0xCCCCCC76,0x00000000, //84
0x00603018,0x00780C7C,0xCCCCCC76,0x00000000, //85
0x00386C38,0x00780C7C,0xCCCCCC76,0x00000000, //86
0x00000000,0x3C666060,0x663C0C06,0x3C000000, //87
0x0010386C,0x007CC6FE,0xC0C0C67C,0x00000000, //88
0x0000C600,0x007CC6FE,0xC0C0C67C,0x00000000, //89
0x00603018,0x007CC6FE,0xC0C0C67C,0x00000000, //8A
0x00006600,0x00381818,0x1818183C,0x00000000, //8B
0x00183C66,0x00381818,0x1818183C,0x00000000, //8C
0x00603018,0x00381818,0x1818183C,0x00000000, //8D
0x00C60010,0x386CC6C6,0xFEC6C6C6,0x00000000, //8E
0x386C3800,0x386CC6C6,0xFEC6C6C6,0x00000000, //8F
0x18306000,0xFE66607C,0x606066FE,0x00000000, //90
0x00000000,0x00CC7636,0x7ED8D86E,0x00000000, //91
0x00003E6C,0xCCCCFECC,0xCCCCCCCE,0x00000000, //92
0x0010386C,0x007CC6C6,0xC6C6C67C,0x00000000, //93
0x0000C600,0x007CC6C6,0xC6C6C67C,0x00000000, //94
0x00603018,0x007CC6C6,0xC6C6C67C,0x00000000, //95
0x003078CC,0x00CCCCCC,0xCCCCCC76,0x00000000, //96
0x00603018,0x00CCCCCC,0xCCCCCC76,0x00000000, //97
0x0000C600,0x00C6C6C6,0xC6C6C67E,0x060C7800, //98
0x00C6007C,0xC6C6C6C6,0xC6C6C67C,0x00000000, //99
0x00C600C6,0xC6C6C6C6,0xC6C6C67C,0x00000000, //9A
0x0018183C,0x66606060,0x663C1818,0x00000000, //9B
0x00386C64,0x60F06060,0x6060E6FC,0x00000000, //9C
0x00006666,0x3C187E18,0x7E181818,0x00000000, //9D
0x00F8CCCC,0xF8C4CCDE,0xCCCCCCC6,0x00000000, //9E
0x000E1B18,0x18187E18,0x18181818,0xD8700000, //9F
0x00183060,0x00780C7C,0xCCCCCC76,0x00000000, //A0
0x000C1830,0x00381818,0x1818183C,0x00000000, //A1
0x00183060,0x007CC6C6,0xC6C6C67C,0x00000000, //A2
0x00183060,0x00CCCCCC,0xCCCCCC76,0x00000000, //A3
0x000076DC,0x00DC6666,0x66666666,0x00000000, //A4
0x76DC00C6,0xE6F6FEDE,0xCEC6C6C6,0x00000000, //A5
0x003C6C6C,0x3E007E00,0x00000000,0x00000000, //A6
0x00386C6C,0x38007C00,0x00000000,0x00000000, //A7
0x00003030,0x00303060,0xC0C6C67C,0x00000000, //A8
0x00000000,0x0000FEC0,0xC0C0C000,0x00000000, //A9
0x00000000,0x0000FE06,0x06060600,0x00000000, //AA
0x00C0C0C2,0xC6CC1830,0x60DC860C,0x183E0000, //AB
0x00C0C0C2,0xC6CC1830,0x66CE9E3E,0x06060000, //AC
0x00001818,0x00181818,0x3C3C3C18,0x00000000, //AD
0x00000000,0x00366CD8,0x6C360000,0x00000000, //AE
0x00000000,0x00D86C36,0x6CD80000,0x00000000, //AF
0x11441144,0x11441144,0x11441144,0x11441144, //B0
0x55AA55AA,0x55AA55AA,0x55AA55AA,0x55AA55AA, //B1
0xDD77DD77,0xDD77DD77,0xDD77DD77,0xDD77DD77, //B2
0x18181818,0x18181818,0x18181818,0x18181818, //B3
0x18181818,0x181818F8,0x18181818,0x18181818, //B4
0x18181818,0x18F818F8,0x18181818,0x18181818, //B5
0x36363636,0x363636F6,0x36363636,0x36363636, //B6
0x00000000,0x000000FE,0x36363636,0x36363636, //B7
0x00000000,0x00F818F8,0x18181818,0x18181818, //B8
0x36363636,0x36F606F6,0x36363636,0x36363636, //B9
0x36363636,0x36363636,0x36363636,0x36363636, //BA
0x00000000,0x00FE06F6,0x36363636,0x36363636, //BB
0x36363636,0x36F606FE,0x00000000,0x00000000, //BC
0x36363636,0x363636FE,0x00000000,0x00000000, //BD
0x18181818,0x18F818F8,0x00000000,0x00000000, //BE
0x00000000,0x000000F8,0x18181818,0x18181818, //BF
0x18181818,0x1818181F,0x00000000,0x00000000, //C0
0x18181818,0x181818FF,0x00000000,0x00000000, //C1
0x00000000,0x000000FF,0x18181818,0x18181818, //C2
0x18181818,0x1818181F,0x18181818,0x18181818, //C3
0x00000000,0x000000FF,0x00000000,0x00000000, //C4
0x18181818,0x181818FF,0x18181818,0x18181818, //C5
0x18181818,0x181F181F,0x18181818,0x18181818, //C6
0x36363636,0x36363637,0x36363636,0x36363636, //C7
0x36363636,0x3637303F,0x00000000,0x00000000, //C8
0x00000000,0x003F3037,0x36363636,0x36363636, //C9
0x36363636,0x36F700FF,0x00000000,0x00000000, //CA
0x00000000,0x00FF00F7,0x36363636,0x36363636, //CB
0x36363636,0x36373037,0x36363636,0x36363636, //CC
0x00000000,0x00FF00FF,0x00000000,0x00000000, //CD
0x36363636,0x36F700F7,0x36363636,0x36363636, //CE
0x18181818,0x18FF00FF,0x00000000,0x00000000, //CF
0x36363636,0x363636FF,0x00000000,0x00000000, //D0
0x00000000,0x00FF00FF,0x18181818,0x18181818, //D1
0x00000000,0x000000FF,0x36363636,0x36363636, //D2
0x36363636,0x3636363F,0x00000000,0x00000000, //D3
0x18181818,0x181F181F,0x00000000,0x00000000, //D4
0x00000000,0x001F181F,0x18181818,0x18181818, //D5
0x00000000,0x0000003F,0x36363636,0x36363636, //D6
0x36363636,0x363636FF,0x36363636,0x36363636, //D7
0x18181818,0x18FF18FF,0x18181818,0x18181818, //D8
0x18181818,0x181818F8,0x00000000,0x00000000, //D9
0x00000000,0x0000001F,0x18181818,0x18181818, //DA
0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF, //DB
0x00000000,0x000000FF,0xFFFFFFFF,0xFFFFFFFF, //DC
0xF0F0F0F0,0xF0F0F0F0,0xF0F0F0F0,0xF0F0F0F0, //DD
0x0F0F0F0F,0x0F0F0F0F,0x0F0F0F0F,0x0F0F0F0F, //DE
0xFFFFFFFF,0xFFFFFF00,0x00000000,0x00000000, //DF
0x00000000,0x0076DCD8,0xD8D8DC76,0x00000000, //E0
0x000078CC,0xCCCCD8CC,0xC6C6C6CC,0x00000000, //E1
0x0000FEC6,0xC6C0C0C0,0xC0C0C0C0,0x00000000, //E2
0x00000000,0xFE6C6C6C,0x6C6C6C6C,0x00000000, //E3
0x000000FE,0xC6603018,0x3060C6FE,0x00000000, //E4
0x00000000,0x007ED8D8,0xD8D8D870,0x00000000, //E5
0x00000000,0x66666666,0x667C6060,0xC0000000, //E6
0x00000000,0x76DC1818,0x18181818,0x00000000, //E7
0x0000007E,0x183C6666,0x663C187E,0x00000000, //E8
0x00000038,0x6CC6C6FE,0xC6C66C38,0x00000000, //E9
0x0000386C,0xC6C6C66C,0x6C6C6CEE,0x00000000, //EA
0x00001E30,0x180C3E66,0x6666663C,0x00000000, //EB
0x00000000,0x007EDBDB,0xDB7E0000,0x00000000, //EC
0x00000003,0x067EDBDB,0xF37E60C0,0x00000000, //ED
0x00001C30,0x60607C60,0x6060301C,0x00000000, //EE
0x0000007C,0xC6C6C6C6,0xC6C6C6C6,0x00000000, //EF
0x00000000,0xFE0000FE,0x0000FE00,0x00000000, //F0
0x00000000,0x18187E18,0x180000FF,0x00000000, //F1
0x00000030,0x180C060C,0x1830007E,0x00000000, //F2
0x0000000C,0x18306030,0x180C007E,0x00000000, //F3
0x00000E1B,0x1B181818,0x18181818,0x18181818, //F4
0x18181818,0x18181818,0xD8D8D870,0x00000000, //F5
0x00000000,0x1818007E,0x00181800,0x00000000, //F6
0x00000000,0x0076DC00,0x76DC0000,0x00000000, //F7
0x00386C6C,0x38000000,0x00000000,0x00000000, //F8
0x00000000,0x00000018,0x18000000,0x00000000, //F9
0x00000000,0x00000000,0x18000000,0x00000000, //FA
0x000F0C0C,0x0C0C0CEC,0x6C6C3C1C,0x00000000, //FB
0x00D86C6C,0x6C6C6C00,0x00000000,0x00000000, //FC
0x0070D830,0x60C8F800,0x00000000,0x00000000, //FD
0x00000000,0x7C7C7C7C,0x7C7C7C00,0x00000000, //FE
0x00000000,0x00000000,0x00000000,0x00000000  //FF
};

        private void makeImg()
        {
            String[] files = Directory.GetFiles(@"E:\fpgaproj\mine.new\", "*.bmp");

            foreach (var item in files)
            {
                Bitmap b = new Bitmap(item);

                FileStream fs = new FileStream(item.Replace(".bmp", ".img"), FileMode.CreateNew, FileAccess.Write);
                for (int j = 0; j < b.Height; j++)
                {
                    for (int i = 0; i < b.Width; i++)
                    {
                        uint val = getpixel(b.GetPixel(i, j));
                        fs.WriteByte((byte)val);
                        fs.WriteByte((byte)(val >> 8));
                    }
                }
                fs.Close();
            }
        }

        public static uint getpixel(Color c)
        {
            uint val = 0;
            val += ((uint)(c.R) >> 3) << (5 + 6);
            val += ((uint)(c.G) >> 2) << (5);
            val += ((uint)(c.B) >> 3);
            return val;
        }
        public static Color setpixel(int v)
        {
            int r = ((v >> 11) & 0x1F) << 3;
            int g = ((v >> 5) & 0x3F) << 2;
            int b = (v & 0x1F) << 3;
            return Color.FromArgb(r, g, b);
        }

        void loadImg(string file, byte[] data, ref int pos, int w, int h)
        {
            Bitmap bmp = new Bitmap(file);
            for (int y = 0; y < h; y++)
            {
                for (int x = 0; x < w; x++)
                {
                    uint val = getpixel(bmp.GetPixel(x, y));
                    data[pos + y * w * 2 + x * 2 + 0] = (byte)((val >> 0) & 0xFF);
                    data[pos + y * w * 2 + x * 2 + 1] = (byte)((val >> 8) & 0xFF);
                }
            }
            pos += w * h * 2;
        }

        static int utf8_to_unicode(byte[] utf8)
        {
            byte c = (byte)utf8[0];

            if (c < 0x80)
            {
                // 1字节 (ASCII)
                return c;
            }
            else if ((c & 0xE0) == 0xC0)
            {
                // 2字节
                return ((c & 0x1F) << 6) | (utf8[1] & 0x3F);
            }
            else if ((c & 0xF0) == 0xE0)
            {
                // 3字节
                return ((c & 0x0F) << 12) |
                       ((utf8[1] & 0x3F) << 6) |
                       (utf8[2] & 0x3F);
            }

            return 0; // 错误字节
        }

        static void proc(int tmp1, int tmp2, int[] font, int[] cnt, int[] map)
        {
            int i = tmp1 - 0xA0;
            int j = tmp2 - 0xA0;
            int chr = 94 * (i - 1) + (j - 1);
            int pos = chr * 8;

            //utf-8 : 00~7F  https://zhuanlan.zhihu.com/p/46216008         https://unifoundry.com/pub/unifont/unifont-15.1.04/

            byte[] gb2312Bytes = new byte[2];
            gb2312Bytes[0] = (byte)tmp1;
            gb2312Bytes[1] = (byte)tmp2;

            string str = Encoding.GetEncoding("GB2312").GetString(gb2312Bytes);
            byte[] utf8Bytes = Encoding.UTF8.GetBytes(str);

            int unicode = utf8_to_unicode(utf8Bytes);
            map[unicode] = (tmp2 << 8) | tmp1;
            int points = putcgbWin2(font, tmp1, tmp2);
            
            if (points > 0)
            {
                cnt[(unicode >> 8) & 0xFF]++;
            }
        }


        static int putcgbWin2(int[] font, int tmp1, int tmp2)
        {
            int points = 0;

            int i = tmp1 - 0xA0;
            int j = tmp2 - 0xA0;
            int chr = 94 * (i - 1) + (j - 1);

            int index = 0;
            byte[] left = new byte[16];
            byte[] right = new byte[16];
            for (j = 0; j < 16; j += 2)
            {
                int p;
                int pos = chr * 8 + index;
                p = (pos < 0 || pos >= font.Length) ? 0 : font[chr * 8 + index];
                index++;
                for (int e = 0; e < 2; e++)
                {
                    int l = 0;
                    for (i = 0; i < 8; i++)
                    {
                        l = l << 1;
                        if ((p & 1) != 0)
                        {
                            l |= 1;
                            points++;
                        }
                        p = p >> 1;
                    }
                    left[j + e] = (byte)l;

                    int r = 0;
                    for (i = 0; i < 8; i++)
                    {
                        r = r << 1;
                        if ((p & 1) != 0)
                        {
                            r |= 1;
                            points++;
                        }
                        p = p >> 1;
                    }
                    right[j + e] = (byte)r;
                }
            }

            return points;
        }
        private void button10_Click(object sender, EventArgs e)
        {
            byte[] data = new byte[1024 * 1024];
            for (int i = 0; i < data.Length; i++)
            {
                data[i] = 0xFF;
            }
            //bios.bin 0x00000 0K~256K 4*page
            {
                FileStream fs = new FileStream("bios.bin", FileMode.Open, FileAccess.Read);
                fs.Read(data, 0, (int)fs.Length);
                fs.Close();
            }
            //char_table 0x40000 256K~256K+64K = 64K
            for (int i = 0; i < char_table.Length; i++)
            {
                int val = 0;
                uint cc = char_table[i];
                for (int n = 0; n < 32; n++)
                {
                    val <<= 1;
                    if ((cc & 1) != 0)
                    {
                        val |= 1;
                    }
                    cc >>= 1;
                }

                data[0x40000 + i * 4 + 0] = (byte)((val >> 0) & 0xFF);
                data[0x40000 + i * 4 + 1] = (byte)((val >> 8) & 0xFF);
                data[0x40000 + i * 4 + 2] = (byte)((val >> 16) & 0xFF);
                data[0x40000 + i * 4 + 3] = (byte)((val >> 24) & 0xFF);
            }

            //cursor    0x50000 256K+64K~256K+128K = 64K 1*page
            StringBuilder sb = new StringBuilder();
            {
                FileStream fs = new FileStream("cur.img", FileMode.Open, FileAccess.Read);
                fs.Read(data, 0x50000, (int)fs.Length);

                for (int i = 0; i < 2048; i++)
                {
                    if ((i & 63) == 0)
                    {
                        sb.AppendLine();
                    }
                    sb.Append("0x" + Util.getHex2(data[0x50000 + i]) + ", ");
                }
                textBox1.Text = sb.ToString();
                fs.Close();
            }

            //HZK16  0x80000 512k
            {
                FileStream fs = new FileStream("HZK16", FileMode.Open, FileAccess.Read);
                fs.Read(data, 0x80000, (int)fs.Length);
                for (int i = 0; i < fs.Length; i++)
                {
                    byte v = data[0x80000 + i];
                    byte v2 = 0;
                    for (int n = 0; n < 8; n++)
                    {
                        v2 <<= 1;
                        if ((v & 1) != 0)
                        {
                            v2 |= 1;
                        }
                        v >>= 1;
                    }
                    data[0x80000 + i] = v2;
                }
                fs.Close();
            }

            {
                FileStream fs = new FileStream("rom.bin", FileMode.Create, FileAccess.Write);
                fs.Write(data, 0, 1024 * 1024);
                fs.Close();
            }


            byte[] char_table_byte = new byte[4 * 1024];
            for (int i = 0; i < char_table.Length; i++)
            {
                int val = 0;
                uint cc = char_table[i];
                for (int n = 0; n < 32; n++)
                {
                    val <<= 1;
                    if ((cc & 1) != 0)
                    {
                        val |= 1;
                    }
                    cc >>= 1;
                }

                char_table_byte[i * 4 + 0] = (byte)((val >> 0) & 0xFF);
                char_table_byte[i * 4 + 1] = (byte)((val >> 8) & 0xFF);
                char_table_byte[i * 4 + 2] = (byte)((val >> 16) & 0xFF);
                char_table_byte[i * 4 + 3] = (byte)((val >> 24) & 0xFF);
            }
            {
                FileStream fs = new FileStream("char_table.bin", FileMode.Create, FileAccess.Write);
                fs.Write(char_table_byte, 0, 4 * 1024);
                fs.Close();
            }



            int[] font = new int[1024 * 1024];
            byte[] hzk = new byte[1024 * 1024];
            int hzkLen;
            {
                {
                    FileStream fs = new FileStream("HZK16", FileMode.Open, FileAccess.Read);
                    fs.Read(data, 0, (int)fs.Length);
                    hzkLen = (int)fs.Length;
                    for (int i = 0; i < hzkLen; i++)
                    {
                        byte v = data[i];
                        byte v2 = 0;
                        for (int n = 0; n < 8; n++)
                        {
                            v2 <<= 1;
                            if ((v & 1) != 0)
                            {
                                v2 |= 1;
                            }
                            v >>= 1;
                        }
                        hzk[i] = v2;
                    }
                    fs.Close();
                }
                {
                    int index = 0;
                    for (int i = 0; i < 1024 * 1024; i += 4)
                    {
                        int val = 0;
                        val |= hzk[i];
                        val |= hzk[i + 1] << 8;
                        val |= hzk[i + 2] << 16;
                        val |= hzk[i + 3] << 24;
                        font[index++] = val;
                    }
                }
                {
                    FileStream fs = new FileStream("HZK16.converted", FileMode.Create, FileAccess.Write);
                    fs.Write(hzk, 0, hzkLen);
                    fs.Close();
                }

            }


            {//make res
                byte[] demo_res = new byte[2 * 1024 * 1024];
                int demo_idx = 0;
                Console.WriteLine("TETRIS_RES 0x" + Util.getHex8(demo_idx));
                loadImg("tetris_res\\0.bmp", demo_res, ref demo_idx, 20, 20);
                loadImg("tetris_res\\1.bmp", demo_res, ref demo_idx, 20, 20);
                loadImg("tetris_res\\2.bmp", demo_res, ref demo_idx, 20, 20);
                loadImg("tetris_res\\3.bmp", demo_res, ref demo_idx, 20, 20);
                loadImg("tetris_res\\4.bmp", demo_res, ref demo_idx, 20, 20);
                loadImg("tetris_res\\5.bmp", demo_res, ref demo_idx, 20, 20);
                loadImg("tetris_res\\6.bmp", demo_res, ref demo_idx, 20, 20);
                loadImg("tetris_res\\7.bmp", demo_res, ref demo_idx, 20, 20);
                loadImg("tetris_res\\8.bmp", demo_res, ref demo_idx, 20, 20);
                loadImg("tetris_res\\9.bmp", demo_res, ref demo_idx, 20, 20);
                loadImg("tetris_res\\10.bmp", demo_res, ref demo_idx, 20, 20);
                loadImg("tetris_res\\11.bmp", demo_res, ref demo_idx, 20, 20);
                loadImg("tetris_res\\12.bmp", demo_res, ref demo_idx, 20, 20);
                loadImg("tetris_res\\13.bmp", demo_res, ref demo_idx, 20, 20);
                loadImg("tetris_res\\14.bmp", demo_res, ref demo_idx, 20, 20);
                loadImg("tetris_res\\15.bmp", demo_res, ref demo_idx, 20, 20);

                Console.WriteLine("MINESWEEPER_RES 0x" + Util.getHex8(demo_idx));
                loadImg("minesweeper_res\\m0.bmp", demo_res, ref demo_idx, 16, 16);
                loadImg("minesweeper_res\\m1.bmp", demo_res, ref demo_idx, 16, 16);
                loadImg("minesweeper_res\\m2.bmp", demo_res, ref demo_idx, 16, 16);
                loadImg("minesweeper_res\\m3.bmp", demo_res, ref demo_idx, 16, 16);
                loadImg("minesweeper_res\\m4.bmp", demo_res, ref demo_idx, 16, 16);
                loadImg("minesweeper_res\\m5.bmp", demo_res, ref demo_idx, 16, 16);
                loadImg("minesweeper_res\\m6.bmp", demo_res, ref demo_idx, 16, 16);
                loadImg("minesweeper_res\\m7.bmp", demo_res, ref demo_idx, 16, 16);
                loadImg("minesweeper_res\\m8.bmp", demo_res, ref demo_idx, 16, 16);
                loadImg("minesweeper_res\\m9.bmp", demo_res, ref demo_idx, 16, 16);
                loadImg("minesweeper_res\\ma.bmp", demo_res, ref demo_idx, 16, 16);//flag
                loadImg("minesweeper_res\\mb.bmp", demo_res, ref demo_idx, 16, 16);//question mark
                loadImg("minesweeper_res\\mc.bmp", demo_res, ref demo_idx, 16, 16);//red mine
                loadImg("minesweeper_res\\md.bmp", demo_res, ref demo_idx, 16, 16);//x mine
                loadImg("minesweeper_res\\me.bmp", demo_res, ref demo_idx, 16, 16);//mine
                loadImg("minesweeper_res\\n0.bmp", demo_res, ref demo_idx, 12, 23);
                loadImg("minesweeper_res\\n1.bmp", demo_res, ref demo_idx, 12, 23);
                loadImg("minesweeper_res\\n2.bmp", demo_res, ref demo_idx, 12, 23);
                loadImg("minesweeper_res\\n3.bmp", demo_res, ref demo_idx, 12, 23);
                loadImg("minesweeper_res\\n4.bmp", demo_res, ref demo_idx, 12, 23);
                loadImg("minesweeper_res\\n5.bmp", demo_res, ref demo_idx, 12, 23);
                loadImg("minesweeper_res\\n6.bmp", demo_res, ref demo_idx, 12, 23);
                loadImg("minesweeper_res\\n7.bmp", demo_res, ref demo_idx, 12, 23);
                loadImg("minesweeper_res\\n8.bmp", demo_res, ref demo_idx, 12, 23);
                loadImg("minesweeper_res\\n9.bmp", demo_res, ref demo_idx, 12, 23);
                loadImg("minesweeper_res\\fi.bmp", demo_res, ref demo_idx, 26, 26);
                loadImg("minesweeper_res\\fj.bmp", demo_res, ref demo_idx, 26, 26);
                loadImg("minesweeper_res\\fm.bmp", demo_res, ref demo_idx, 26, 26);
                loadImg("minesweeper_res\\fo.bmp", demo_res, ref demo_idx, 26, 26);
                loadImg("minesweeper_res\\ft.bmp", demo_res, ref demo_idx, 26, 26);

                demo_idx &= ~(0x0F); demo_idx += 0x10;
                Console.WriteLine("JPG0_RES 0x" + Util.getHex8(demo_idx));
                {
                    FileStream fs = new FileStream("tjpg/test0.jpg", FileMode.Open, FileAccess.Read);
                    fs.Read(demo_res, demo_idx, (int)fs.Length);
                    demo_idx += (int)fs.Length;
                    fs.Close();
                }

                demo_idx &= ~(0x0F); demo_idx += 0x10;
                Console.WriteLine("JPG1_RES 0x" + Util.getHex8(demo_idx));
                {
                    FileStream fs = new FileStream("tjpg/test1.jpg", FileMode.Open, FileAccess.Read);
                    fs.Read(demo_res, demo_idx, (int)fs.Length);
                    demo_idx += (int)fs.Length;
                    fs.Close();
                }

                demo_idx &= ~(0x0F); demo_idx += 0x10;
                Console.WriteLine("CHAR_TABLE 0x" + Util.getHex8(demo_idx));
                {
                    for (int i = 0; i < 4 * 1024; i++)
                    {
                        demo_res[demo_idx + i] = char_table_byte[i];
                    }
                    demo_idx += 4 * 1024;
                }

                demo_idx &= ~(0x0F); demo_idx += 0x10;
                Console.WriteLine("HZK 0x" + Util.getHex8(demo_idx));
                {
                    for (int i = 0; i < hzkLen; i++)
                    {
                        demo_res[demo_idx + i] = data[i];
                    }
                    demo_idx += hzkLen;
                }

                writeObj(demo_res, ref demo_idx, "aaa");
                writeObj(demo_res, ref demo_idx, "cube");
                writeObj(demo_res, ref demo_idx, "sphere");
                writeObj(demo_res, ref demo_idx, "sphere2");
                writeObj(demo_res, ref demo_idx, "t34");

                convObj("aaa");
                convObj("cube");
                convObj("sphere");
                convObj("sphere2");
                convObj("t34");

                demo_idx &= ~(0xFF); demo_idx += 0x100;
                writeTexture(demo_res, ref demo_idx, "aaa");
                writeTexture(demo_res, ref demo_idx, "cube");
                writeTexture(demo_res, ref demo_idx, "sphere");

                demo_idx &= ~(0x0F); demo_idx += 0x10;
                Console.WriteLine("END 0x" + Util.getHex8(demo_idx));
                {
                    FileStream fs = new FileStream("demo.res", FileMode.Create, FileAccess.Write);
                    fs.Write(demo_res, 0, demo_idx);
                    fs.Close();
                }

            }

            {//make res
                byte[] jsdemo_res = new byte[2 * 1024 * 1024];
                int demo_idx = 0;

                demo_idx &= ~(0x0F); demo_idx += 0x10;
                Console.WriteLine("CHAR_TABLE 0x" + Util.getHex8(demo_idx));
                {
                    for (int i = 0; i < 4 * 1024; i++)
                    {
                        jsdemo_res[demo_idx + i] = char_table_byte[i];
                    }
                    demo_idx += 4 * 1024;
                }

                demo_idx &= ~(0x0F); demo_idx += 0x10;
                Console.WriteLine("HZK 0x" + Util.getHex8(demo_idx));
                {
                    for (int i = 0; i < hzkLen; i++)
                    {
                        jsdemo_res[demo_idx + i] = hzk[i];
                    }
                    demo_idx += hzkLen;
                }


                int[] cnt = new int[256];
                int[] map = new int[65536];
                int[] map0 = new int[256];
                int[] map1 = new int[65536];
                for (int tmp1 = 0; tmp1 < 256; tmp1++)
                {
                    for (int tmp2 = 0; tmp2 < 256; tmp2++)
                    {
                        if (tmp1 >= 0xA0 && tmp2 >= 0xA0)
                        {
                            proc(tmp1, tmp2, font, cnt, map);
                        }
                    }
                }

                int indexMap = 0;

                for (int tmp1 = 0; tmp1 < 256; tmp1++)
                {
                    if (cnt[tmp1] != 0)
                    {
                        map0[tmp1] = indexMap;
                        for (int i = 0; i < 256; i++)
                        {
                            map1[(indexMap << 8) + i] = map[(tmp1 << 8) + i];
                        }
                        indexMap++;
                    }
                }

                {//test
                    int uni = utf8_to_unicode(new byte[] { 0xE4, 0xBD, 0xA0 });
                    int tmp = map0[(uni >> 8) & 0xFF];
                    int gb = map1[(tmp << 8) + (uni & 0xFF)];
                }



                demo_idx &= ~(0x0F); demo_idx += 0x10;
                Console.WriteLine("U2GB 0x" + Util.getHex8(demo_idx));
                {
                    for (int i = 0; i < 256; i++)
                    {
                        jsdemo_res[demo_idx + i] = (byte)map0[i];
                    }
                    demo_idx += 256;

                    for (int j = 0; j < indexMap; j++)
                    {
                        for (int i = 0; i < 256; i++)
                        {
                            jsdemo_res[demo_idx + i * 2] = (byte)(map1[(j << 8) + i] & 0xFF);
                            jsdemo_res[demo_idx + i * 2 + 1] = (byte)(map1[(j << 8) + i] >> 8);
                        }
                        demo_idx += 512;
                    }
                }



                demo_idx &= ~(0x0F); demo_idx += 0x10;
                Console.WriteLine("END 0x" + Util.getHex8(demo_idx));
                {
                    FileStream fs = new FileStream("jsdemo.res", FileMode.Create, FileAccess.Write);
                    fs.Write(jsdemo_res, 0, demo_idx);
                    fs.Close();
                }

            }

            MessageBox.Show("rom.bin ok");

        }

        private void clock_res()
        {


            byte[] char_table_byte = new byte[4 * 1024];
            for (int i = 0; i < char_table.Length; i++)
            {
                int val = 0;
                uint cc = char_table[i];
                for (int n = 0; n < 32; n++)
                {
                    val <<= 1;
                    if ((cc & 1) != 0)
                    {
                        val |= 1;
                    }
                    cc >>= 1;
                }

                char_table_byte[i * 4 + 0] = (byte)((val >> 0) & 0xFF);
                char_table_byte[i * 4 + 1] = (byte)((val >> 8) & 0xFF);
                char_table_byte[i * 4 + 2] = (byte)((val >> 16) & 0xFF);
                char_table_byte[i * 4 + 3] = (byte)((val >> 24) & 0xFF);
            }


            {//make res
                byte[] clock_res = new byte[2 * 1024 * 1024];
                int clock_idx = 0;

                clock_idx &= ~(0x0F); clock_idx += 0x10;
                Console.WriteLine("CHAR_TABLE 0x" + Util.getHex8(clock_idx));
                {
                    for (int i = 0; i < 4 * 1024; i++)
                    {
                        clock_res[clock_idx + i] = char_table_byte[i];
                    }
                    clock_idx += 4 * 1024;
                }


                clock_idx &= ~(0x0F); clock_idx += 0x10;
                Console.WriteLine("END 0x" + Util.getHex8(clock_idx));
                {
                    FileStream fs = new FileStream("clock.res", FileMode.Create, FileAccess.Write);
                    fs.Write(clock_res, 0, clock_idx);
                    fs.Close();
                }
            }


            MessageBox.Show("rom.bin ok");

        }
        static void writeValue(byte[] demo_res, ref int index, int value)
        {
            demo_res[index + 0] = (byte)(value & 0xFF);
            demo_res[index + 1] = (byte)(value >> 8 & 0xFF);
            demo_res[index + 2] = (byte)(value >> 16 & 0xFF);
            demo_res[index + 3] = (byte)(value >> 24 & 0xFF);
            index += 4;
        }
        static void writeValue(byte[] demo_res, ref int index, float fvalue)
        {
            uint value = Util.convert(fvalue);
            demo_res[index + 0] = (byte)(value & 0xFF);
            demo_res[index + 1] = (byte)(value >> 8 & 0xFF);
            demo_res[index + 2] = (byte)(value >> 16 & 0xFF);
            demo_res[index + 3] = (byte)(value >> 24 & 0xFF);
            index += 4;
        }

        public static void writeObj(byte[] demo_res, ref int index, string file)
        {
            index &= ~(0x0F); index += 0x10;
            Console.WriteLine("obj " + file + " 0x" + Util.getHex8(index));
            ObjData obj = read3DObj(file);

            writeValue(demo_res,ref index ,obj.vertexesCount );
            for (int i = 0; i < obj.vertexesCount * 3; i++)
            {
                writeValue(demo_res, ref index, obj.vertexes[i]);
            }
            //---------------------------------------------------------------------------
            writeValue(demo_res, ref index, obj.textureMapCount);
            for (int i = 0; i < obj.textureMapCount * 2; i++)
            {
                writeValue(demo_res, ref index, obj.textureMap[i]);
            }
            //---------------------------------------------------------------------------
            writeValue(demo_res, ref index, obj.faceCount);
            for (int i = 0; i < obj.faceCount * 3; i++)
            {
                writeValue(demo_res, ref index, obj.faceVerticles[i]);
            }
            for (int i = 0; i < obj.faceCount * 3; i++)
            {
                writeValue(demo_res, ref index, obj.faceTexture[i]);
            }
        }

        public static void convObj(string file)
        {
            ObjData obj = read3DObj(file);
            byte[] demo_res = new byte[2 * 1024 * 1024];
            int demo_idx = 0;

            writeValue(demo_res, ref demo_idx, obj.vertexesCount);
            for (int i = 0; i < obj.vertexesCount * 3; i++)
            {
                writeValue(demo_res, ref demo_idx, obj.vertexes[i]);
            }
            //---------------------------------------------------------------------------
            writeValue(demo_res, ref demo_idx, obj.textureMapCount);
            for (int i = 0; i < obj.textureMapCount * 2; i++)
            {
                writeValue(demo_res, ref demo_idx, obj.textureMap[i]);
            }
            //---------------------------------------------------------------------------
            writeValue(demo_res, ref demo_idx, obj.faceCount);
            for (int i = 0; i < obj.faceCount * 3; i++)
            {
                writeValue(demo_res, ref demo_idx, obj.faceVerticles[i]);
            }
            for (int i = 0; i < obj.faceCount * 3; i++)
            {
                writeValue(demo_res, ref demo_idx, obj.faceTexture[i]);
            }

            //demo_idx &= ~(0x0F); demo_idx += 0x10;
            {
                FileStream fs = new FileStream("3dobj\\" + file + ".b3o", FileMode.Create, FileAccess.Write);
                fs.Write(demo_res, 0, demo_idx);
                fs.Close();

            }
        }

        public static void writeTexture(byte[] demo_res, ref int index, string file)
        {
            Console.WriteLine("texture " + file + " 0x" + Util.getHex8(index));
            Bitmap img = (Bitmap)Bitmap.FromFile("3dobj\\" + file + ".bmp");
            int[] texture = new int[256 * 256];

            for (int j = 0; j < 256; j++)
            {
                for (int i = 0; i < 256; i++)
                {
                    texture[i + (255 - j) * 256] = img.GetPixel(i * img.Width / 256, j * img.Height / 256).ToArgb();
                }
            }
            
            for (int i = 0; i < 256 * 256; i++)
            {
                int value = Util.getRGB565(texture[i]);
                demo_res[index + 0] = (byte)(value & 0xFF);
                demo_res[index + 1] = (byte)(value >> 8 & 0xFF);
                index += 2;
            }
        }

        public static ObjData read3DObj(string file)
        {
            ObjData obj = new ObjData();
            FileStream fs = new FileStream("3dobj\\" + file + ".obj", FileMode.Open, FileAccess.Read);

            StreamReader sr = new StreamReader(fs);
            obj.vertexesCount = 0;
            obj.textureMapCount = 0;
            obj.faceCount = 0;
            while (true)
            {
                string line = sr.ReadLine();
                if (line == null) break;

                line = line.Trim();

                if (line.StartsWith("v "))
                {// v  -0.0873 13.3457 -3.5094
                    obj.vertexesCount++;
                }
                else if (line.StartsWith("vt "))
                {//vt 0.0000 1.0000 0.0000
                    obj.textureMapCount++;
                }
                else if (line.StartsWith("f "))
                {//f 1/1 2/2 3/3 
                    obj.faceCount++;
                }
            }
            sr.Close();
            fs.Close();

            obj.vertexes = new float[obj.vertexesCount * 3];//3*n
            obj.textureMap = new float[obj.textureMapCount * 2];//2*n
            obj.faceVerticles = new int[obj.faceCount * 3];//3*n
            obj.faceTexture = new int[obj.faceCount * 3];//3*n

            fs = new FileStream("3dobj\\" + file + ".obj", FileMode.Open, FileAccess.Read);

            sr = new StreamReader(fs);
            int verticleCount = 0;
            int textureMapCount = 0;
            int faceCount = 0;
            while (true)
            {
                string line = sr.ReadLine();
                if (line == null) break;

                line = line.Trim();

                if (line.StartsWith("v "))
                {// v  -0.0873 13.3457 -3.5094
                    var s = line.Replace("  ", " ").Split(' ');
                    obj.vertexes[verticleCount] = float.Parse(s[1]);
                    verticleCount++;
                    obj.vertexes[verticleCount] = float.Parse(s[2]);
                    verticleCount++;
                    obj.vertexes[verticleCount] = float.Parse(s[3]);
                    verticleCount++;
                }
                else if (line.StartsWith("vt "))
                {//vt 0.0000 1.0000 0.0000
                    var s = line.Split(' ');
                    obj.textureMap[textureMapCount] = float.Parse(s[1]);
                    textureMapCount++;
                    obj.textureMap[textureMapCount] = float.Parse(s[2]);
                    textureMapCount++;
                }
                else if (line.StartsWith("f "))
                {//f 1/1 2/2 3/3 
                    var s = line.Split(' ');
                    var s1 = s[1].Split('/');
                    var s2 = s[2].Split('/');
                    var s3 = s[3].Split('/');
                    obj.faceVerticles[faceCount] = int.Parse(s1[0]) - 1;
                    obj.faceTexture[faceCount] = int.Parse(s1[1]) - 1;
                    faceCount++;
                    obj.faceVerticles[faceCount] = int.Parse(s2[0]) - 1;
                    obj.faceTexture[faceCount] = int.Parse(s2[1]) - 1;
                    faceCount++;
                    obj.faceVerticles[faceCount] = int.Parse(s3[0]) - 1;
                    obj.faceTexture[faceCount] = int.Parse(s3[1]) - 1;
                    faceCount++;
                }
            }
            sr.Close();
            fs.Close();

            return obj;
        }

        private void button8_Click(object sender, EventArgs e)
        {
            int totalM = int.Parse(this.textBox3.Text);

            byte[] data = new byte[totalM * 1024 * 1024];
            Random r = new Random();
            r.NextBytes(data);
            FileStream fs = new FileStream("rom.bin", FileMode.Create, FileAccess.Write);
            fs.Write(data, 0, totalM * 1024 * 1024);
            fs.Close();
            MessageBox.Show("rom.bin ok");

        }

        private void button9_Click(object sender, EventArgs e)
        {
            int totalM = int.Parse(this.textBox3.Text);

            byte[] buff = new byte[totalM * 1024 * 1024];

            FileStream fs = new FileStream("rom.bin", FileMode.Open, FileAccess.Read);
            fs.Read(buff, 0, totalM * 1024 * 1024);
            fs.Close();


            int err = 0;
            for (int i = 0; i < totalM * 256; i++)
            {
                byte[] data = readSectorMem(i);

                for (int j = 0; j < 4096; j++)
                {
                    if (buff[i * 4096 + j] != data[j])
                    {
                        err++;
                    }
                }
                this.Text = i + "";
            }

            textBox1.Text = err + ",\r\n";

        }
        




        public uint CH375_DAT = 0x5A000000;
        public uint CH375_DAT4 = 0x5A000004;
        public uint CH375_A0 = 0x5A000004;
        public uint CH375_CS = 0x5A000008;
        public uint CH375_RD = 0x5A00000C;
        public uint CH375_WR = 0x5A000010;

        public uint CMD = 0x01;//01H GET_IC_VER 版本号 获取芯片及固件版本
        public uint DATA = 0x00;//01H GET_IC_VER 版本号 获取芯片及固件版本

        public int GET_IC_VER = 0x01;//01H GET_IC_VER 版本号 获取芯片及固件版本
        public int CHECK_EXIST = 0x06;//06H CHECK_EXIST 任意数据 按位取反 测试工作状态
        public int DISK_INIT = 0x51;//51H DISK_INIT 产生中断 初始化USB存储设备
        public int GET_STATUS = 0x22;//22H GET_STATUS 中断状态 获取中断状态并取消请求
        public int TEST_CONNECT = 0x16;//16H TEST_CONNECT （等2uS） 连接状态 检查USB 设备的连接状态
        public int SET_USB_MODE = 0x15;//15H SET_USB_MODE 模式代码 （等20uS） 操作状态 设置USB 工作模式
        public int DISK_SIZE = 0x53;//53H DISK_SIZE 产生中断 获取USB 存储设备的容量
        public int RD_USB_DATA = 0x28;//28H RD_USB_DATA 数据长度 从当前USB中断的 数据流 端点缓冲区读取数据块
        public int DISK_READ = 0x54;//54H DISK_READ LBA 地址 产生中断 从USB存储设备读数据块
        public int DISK_RD_GO = 0x55;//55H DISK_RD_GO 产生中断 继续USB 存储设备的读操作
        public int RESET_ALL = 0x05;//05H RESET_ALL （等40mS） 执行硬件复位


        private void setCMD(int cmd)
        {
            this.mainForm.setmem(CH375_WR, 1);//WR#

            this.mainForm.setmem(CH375_A0, CMD);//A0 当A0=1 时可以写命令，当A0=0 时可以读写数据
            this.mainForm.setmem(CH375_DAT, (byte)cmd);
            this.mainForm.setmem(CH375_WR, 0);//WR#
            this.mainForm.setmem(CH375_WR, 1);//WR#
        }
        private void setDATA(int data)
        {
            this.mainForm.setmem(CH375_A0, (byte)DATA);//A0 当A0=1 时可以写命令，当A0=0 时可以读写数据
            this.mainForm.setmem(CH375_DAT, (byte)data);
            this.mainForm.setmem(CH375_WR, 0);//WR#
            this.mainForm.setmem(CH375_WR, 1);//WR#
        }
        private uint getDATA()
        {
            this.mainForm.setmem(CH375_A0, (byte)DATA);//A0 当A0=1 时可以写命令，当A0=0 时可以读写数据
            this.mainForm.setmem(CH375_RD, 0);//RD#
            uint val = this.mainForm.getmem(CH375_DAT, null);
            this.mainForm.setmem(CH375_RD, 1);//RD#
            return val;
        }
        private uint getDATA4()
        {
            this.mainForm.setmem(CH375_A0, (byte)DATA);//A0 当A0=1 时可以写命令，当A0=0 时可以读写数据
            //this.mainForm.setmem(CH375_RD, 0);//RD#
            uint val = this.mainForm.getmem(CH375_DAT4, null);
            //this.mainForm.setmem(CH375_RD, 1);//RD#
            return val;
        }

        private uint waitForInt()
        {
            while (true)
            {
                uint tmp = this.mainForm.getmem(CH375_DAT, null);
                if ((tmp & 0x100) == 0)
                {
                    break;
                }
            }

            setCMD(GET_STATUS);
            uint val = getDATA();
            return val;
        }

        private void setMode(int mode)
        {
            setCMD(SET_USB_MODE);
            setDATA(mode);
        }

        private void button11_Click(object sender, EventArgs e)
        {
            this.mainForm.setmem(CH375_CS, 0);//CS#

            setCMD(RESET_ALL);

            Thread.Sleep(100);

            setCMD(GET_IC_VER);

            uint val = getDATA();

            setCMD(CHECK_EXIST);
            setDATA(0x55);

            uint val2 = getDATA();


            this.mainForm.setmem(CH375_CS, 1);//CS#

            this.textBox1.Text += Util.getHex8(val) + ", " + Util.getHex8(val2) + "\r\n";
        }


        private void button12_Click(object sender, EventArgs e)
        {
            uint val;
            this.mainForm.setmem(CH375_CS, 0);//CS#

            setMode(5);//建议在没有USB 设备时使用模式5，插入USB 设备后先进入模式7再换到模式6。

            val = waitForInt();
            this.textBox1.Text += Util.getHex8(val) + "\r\n";

            if (val != 0x115)//15H USB_INT_CONNECT 检测到USB设备连接事件
            {
                this.mainForm.setmem(CH375_CS, 1);//CS#
                return;
            }

            setMode(7);

            setMode(6);
            val = waitForInt();
            this.textBox1.Text += Util.getHex8(val) + "\r\n";

            if (val != 0x115)//15H USB_INT_CONNECT 检测到USB设备连接事件
            {
                this.mainForm.setmem(CH375_CS, 1);//CS#
                return;
            }


            setCMD(DISK_INIT);

            val = waitForInt();


            this.mainForm.setmem(CH375_CS, 1);//CS#
            this.textBox1.Text += Util.getHex8(val) + "\r\n";
        }

        private void button13_Click(object sender, EventArgs e)
        {
            uint val;
            this.mainForm.setmem(CH375_CS, 0);//CS#

            setCMD(DISK_SIZE);

            val = waitForInt();

            setCMD(RD_USB_DATA);

            //前4个字节以高字节在前组成的双字数据是USB 存储设备的总扇区数，
            //后4个字节以高字节在前组成的双字数据是每个扇区的字节数，
            //两个数据相乘的结果就是以字节为单位的USB存储设备的总容量。
            uint val1 = getDATA();
            if ((val1 & 0xFF) != 8)
            {
                this.mainForm.setmem(CH375_CS, 1);//CS#
                return;
            }
            uint secCount = 0;
            uint val2 = getDATA();
            secCount |= (val2 & 0xFF) << 24;
            uint val3 = getDATA();
            secCount |= (val3 & 0xFF) << 16;
            uint val4 = getDATA();
            secCount |= (val4 & 0xFF) << 8;
            uint val5 = getDATA();
            secCount |= (val5 & 0xFF);

            uint secSize = 0;
            uint val6 = getDATA();
            secSize |= (val6 & 0xFF) << 24;
            uint val7 = getDATA();
            secSize |= (val7 & 0xFF) << 16;
            uint val8 = getDATA();
            secSize |= (val8 & 0xFF) << 8;
            uint val9 = getDATA();
            secSize |= (val9 & 0xFF);

            this.mainForm.setmem(CH375_CS, 1);//CS#
            this.textBox1.Text += secCount + "," + secSize + "\r\n";

        }

        private uint[] getData(int lba)
        {
            uint val = 0;
            this.mainForm.setmem(CH375_CS, 0);//CS#
            //该命令从USB 存储设备读取数据块。读取数据块以扇区为基本单位，需要两组参数：起始地址和数据长度，
            //起始地址是以4个字节表示的线性扇区号LBA 地址，数据长度是以1个字节表示的扇区数。
            //该命令需要5 个输入数据，依次是LBA 地址的最低字节，LBA地址的较低字节，LBA地址的较高字节，
            //LBA 地址的最高字节，扇区数。该命令可以在容量高达2000GB 的USB 存储设备中任意读取1 至255
            //个扇区的数据。该命令需要与下面的DISK_RD_GO命令配合使用。

            setCMD(DISK_READ);
            setDATA(lba & 0xFF);
            setDATA((lba >> 8) & 0xFF);
            setDATA((lba >> 16) & 0xFF);
            setDATA((lba >> 24) & 0xFF);
            setDATA(1);

            val = waitForInt();

            uint[] data = new uint[128];

            for (int i = 0; i < 8; i++)
            {
                if (i != 0)
                {
                    setCMD(DISK_RD_GO);
                    val = waitForInt();
                }
                setCMD(RD_USB_DATA);
                uint len = getDATA();
                for (int j = 0; j < 16; j++)
                {
                    //uint temp = getDATA();
                    data[i * 16 + j] = 0;
                    data[i * 16 + j] |= (getDATA() & 0xFF) << 0;
                    data[i * 16 + j] |= (getDATA() & 0xFF) << 8;
                    data[i * 16 + j] |= (getDATA() & 0xFF) << 16;
                    data[i * 16 + j] |= (getDATA() & 0xFF) << 24;
                }
            }
            setCMD(DISK_RD_GO);
            val = waitForInt();

            this.mainForm.setmem(CH375_CS, 1);//CS#
            return data;
        }
        private uint[] getData4(int lba)
        {
            uint val = 0;
            this.mainForm.setmem(CH375_CS, 0);//CS#
            //该命令从USB 存储设备读取数据块。读取数据块以扇区为基本单位，需要两组参数：起始地址和数据长度，
            //起始地址是以4个字节表示的线性扇区号LBA 地址，数据长度是以1个字节表示的扇区数。
            //该命令需要5 个输入数据，依次是LBA 地址的最低字节，LBA地址的较低字节，LBA地址的较高字节，
            //LBA 地址的最高字节，扇区数。该命令可以在容量高达2000GB 的USB 存储设备中任意读取1 至255
            //个扇区的数据。该命令需要与下面的DISK_RD_GO命令配合使用。

            setCMD(DISK_READ);
            setDATA(lba & 0xFF);
            setDATA((lba >> 8) & 0xFF);
            setDATA((lba >> 16) & 0xFF);
            setDATA((lba >> 24) & 0xFF);
            setDATA(1);

            val = waitForInt();

            uint[] data = new uint[128];

            for (int i = 0; i < 8; i++)
            {
                if (i != 0)
                {
                    setCMD(DISK_RD_GO);
                    val = waitForInt();
                }
                setCMD(RD_USB_DATA);
                uint len = getDATA();
                for (int j = 0; j < 16; j++)
                {
                    uint temp = getDATA4();
                    data[i * 16 + j] = temp;
                }
            }
            setCMD(DISK_RD_GO);
            val = waitForInt();

            this.mainForm.setmem(CH375_CS, 1);//CS#
            return data;
        }
        private void button14_Click(object sender, EventArgs e)
        {
            FileStream fs = new FileStream("e:\\out.bin", FileMode.Create, FileAccess.Write);
            int lba = 0;
            while (lba < 1)
            {
                uint[] data;
                if (checkBox2.Checked)
                {
                    data = getData4(lba);
                }
                else {
                    data = getData(lba);
                }
                lba++;
                this.Text = lba + "";
                StringBuilder sb = new StringBuilder();
                for (int i = 0; i < 128; i++)
                {
                    if ((i & 3) == 0)
                    {
                        sb.Append("\r\n");
                    }
                    sb.Append(Util.getHex8(data[i]));
                    sb.Append(" ");
                }

                byte[] bdata = new byte[512];
                for (int i = 0; i < 128; i++)
                {
                    bdata[i * 4 + 0] = (byte)((data[i] >> 0) & 0xFF);
                    bdata[i * 4 + 1] = (byte)((data[i] >> 8) & 0xFF);
                    bdata[i * 4 + 2] = (byte)((data[i] >> 16) & 0xFF);
                    bdata[i * 4 + 3] = (byte)((data[i] >> 24) & 0xFF);
                }
                fs.Write(bdata, 0, 512);
                fs.Flush();
                //this.textBox4.Text = Util.getHex8(val) + "\r\n";
                this.textBox1.Text = sb.ToString();

                Application.DoEvents();
            }
            fs.Close();
        }

        private void textBox2_TextChanged(object sender, EventArgs e)
        {

        }

        private void button15_Click(object sender, EventArgs e)
        {
            spiCSOn();
            spiSend(0xA3);
            spiSend(0x00);
            spiSend(0x00);
            spiSend(0x00);
            spiCSOff();
            //High Performance Mode A3h dummy dummy dummy
        }

        private void button16_Click(object sender, EventArgs e)
        {
            FileStream fs = new FileStream("romdump.bin", FileMode.Create, FileAccess.Write);
            //FileStream fstext = new FileStream("romdump.bin.text", FileMode.Create, FileAccess.Write);
            //StreamWriter sw = new StreamWriter(fstext);
            int total = int.Parse(this.textBox3.Text) * 256;

            for (int i = 0; i < total; i++)
            {
                byte[] data = this.readSectorMem(i);
                //byte[] data = this.readSector(i);

                fs.Write(data, 0, 4096);
                fs.Flush();

                //StringBuilder sb = new StringBuilder();
                //for (int j = 0; j < 4; j++)
                //{
                //    sb.Append(Util.getHex2(data[j]));
                //    sb.Append(" ");
                //}
                //sb.Append("\r\n");
                //sw.Write(sb);
                //sw.Flush();
                //textBox1.Text = sb.ToString();
                this.Text = i + "";
            }

            fs.Close();
            //fstext.Close();
        }

        private void button17_Click(object sender, EventArgs e)
        {
            int sector = int.Parse(this.textBox2.Text);
            
            byte[] buff = new byte[4096];
            FileStream fs = new FileStream("temp.txt", FileMode.Create, FileAccess.Write);
            StreamWriter sw = new StreamWriter(fs);
            Random r = new Random();
            r.NextBytes(buff);
            for (int i = 0; i < 4096; i++)
            {
                if ((i & 15) == 0)
                {
                    sw.WriteLine();
                }
                sw.Write(Util.getHex2(buff[i]) + " ");
            }
            sw.Flush();
            fs.Close();
            this.writeSector(sector, buff, 0, true, false);
            this.textBox1.Text = "ok";
        }

        private void button18_Click(object sender, EventArgs e)
        {

            spiCSOn();
            spiSend(0x80 + (0x20 <<1) + 1);
            textBox1.Text = " " + Util.getHex2(spiRec());
            spiCSOff();

            spiCSOn();
            spiSend(0x80 + (0x00 << 1) + 1);
            textBox1.Text += " " + Util.getHex2(spiRec());
            spiCSOff();

            spiCSOn();
            spiSend(0x80 + (0x01 << 1) + 1);
            textBox1.Text += " " + Util.getHex2(spiRec());
            spiCSOff();

            spiCSOn();
            spiSend(0x80 + (0x02 << 1) + 1);
            textBox1.Text += " " + Util.getHex2(spiRec());
            spiCSOff();

        }

        private void button19_Click(object sender, EventArgs e)
        {
            //Power-down B9h
            spiCSOn();
            spiSend(0xB9);
            spiCSOff();

            //Release Power down or
            //HPM / Device ID
            //ABh dummy dummy dummy (ID7-ID0) (5)
            spiCSOn();
            spiSend(0xAB);
            spiSend(0x00);//status
            spiSend(0x00);//status
            spiSend(0x00);//status
            uint a = spiRec();
            spiCSOff();

            spiCSOn();
            //Write Status Register 01h (S7–S0) (S15-S8)
            spiSend(0x01);//status
            spiSend(0x00);//status
            spiSend(0x02);//status
            spiCSOff();

        }

        void draw(Bitmap bmp, int x, int y, byte[] data, int pos)
        {
            for (int j = 0; j < 16; j++)
            {
                for (int i = 0; i < 16; i++)
                {
                    Color c;
                    byte b = data[pos + (j << 1) + (i >> 3)];
                    b >>= (7-(i & 7));
                    b &= 1;
                    if (b != 0)
                    {
                        c = Color.White;
                    }
                    else
                    {
                        c = Color.Black;
                    }
                    bmp.SetPixel(x + i, y + j, c);
                }
            }
        }
        private void button20_Click(object sender, EventArgs e)
        {
            //267616 / 32 byte
            //8363

            Bitmap bmp = new Bitmap(64 * 16, 131*16);
            byte[] data = new byte[1024*1024];
            FileStream fs = new FileStream("HZK16", FileMode.Open, FileAccess.Read);
            fs.Read(data, 0, 267616);
            int pos = 0;
            for (int j = 0; j < 131; j++)
            {
                for (int i = 0; i < 64; i++)
                {
                    draw( bmp, i*16, j*16, data, pos);
                    pos += 32;
                }
            }
            fs.Close();
            bmp.Save("d:\\hzk.bmp");
        }

        private void button21_Click(object sender, EventArgs e)
        {
            var shift = 512 * 1024 / 4096;
            write_rom(shift, 0, false);
        }

        void write_rom(int shift, int readShift, bool isbyte){
            
            byte[] buff = new byte[1 * 1024 * 1024];

            FileStream fs = new FileStream("bios_simple.bin", FileMode.Open, FileAccess.Read);
            fs.Read(buff, 0, (int)fs.Length);
            int totalPages = (int)(fs.Length / 4096) + 1;
            fs.Close();


            for (int i = 0; i < totalPages; i++)
            {
                int errcount = 0;
                while (true)
                {
                    try
                    {
                        byte[] data = readSector(i + readShift);
                        bool isSame = true;
                        for (int j = 0; j < 4096; j++)
                        {
                            if (buff[i * 4096 + j] != data[j])
                            {
                                isSame = false;
                                break;
                            }
                        }
                        if (!isSame)
                        {
                            Console.WriteLine("write sec:" + i);
                            if (isbyte)
                            {
                                writeSectorByte(i + shift, buff, i * 4096);//4k / sec
                            }
                            else
                            {
                                writeSector(i + shift, buff, i * 4096, true, false);//4k / sec
                            }
                            
                            errcount++;



                            if (errcount > 3)
                            {
                                Console.WriteLine("error");
                                return;
                            }
                        }
                        data = readSector(i + readShift);
                        int err = 0;
                        for (int j = 0; j < 4096; j++)
                        {
                            if (buff[i * 4096 + j] != data[j])
                            {
                                err++;
                                //Console.WriteLine(Util.getHex8(i * 4096 + j) + ":" + Util.getHex2(buff[i * 4096 + j]) + "," + Util.getHex2(data[j]));
                            }
                        }
                        if (err == 0)
                        {
                            break;
                        }
                    }
                    catch (Exception ex)
                    {
                    }
                    this.Text = "err";
                    spiCSOn();
                    spiCSOff();
                }
                this.Text = i + "";
            }
            textBox1.Text = "ok";
        }


        void putcgbWin(int[] font, int tmp1, int tmp2)
        {

            int i = tmp1 - 0xA0;
            int j = tmp2 - 0xA0;
            int chr = 94 * (i - 1) + (j - 1);
            Console.Write("\r\n");

            int index = 0;
            byte[] left = new byte[16];
            byte[] right = new byte[16];
            for (j = 0; j < 16; j += 2)
            {
                int p;
                p = font[chr * 8 + index];
                index++;
                for (int e = 0; e < 2; e++)
                {
                    int l = 0;
                    for (i = 0; i < 8; i++)
                    {
                        l = l << 1;
                        if ((p & 1) != 0)
                        {
                            Console.Write("[]");
                            l |= 1;
                        }
                        else
                        {
                            Console.Write("__");
                        }
                        p = p >> 1;
                    }
                    left[j+e] = (byte)l;

                    int r = 0;
                    for (i = 0; i < 8; i++)
                    {
                        r = r << 1;
                        if ((p & 1) != 0)
                        {
                            Console.Write("[]");
                            r |= 1;
                        }
                        else
                        {
                            Console.Write("__");
                        }
                        p = p >> 1;
                    }
                    right[j+e] = (byte)r;
                    Console.Write("\r\n");
                }
            }

            for (j = 0; j < 16; j++)
            {
                string s = Convert.ToString(left[j], 16);
                if (left[j] >= 16)
                {

                    Console.Write("0x" + s + ", ");
                }
                else
                {
                    Console.Write("0x0" + s + ", ");
                }
            }
            Console.Write("\r\n");

            for (j = 0; j < 16; j++)
            {
                string s = Convert.ToString(right[j], 16);
                if (right[j] >= 16)
                {

                    Console.Write("0x" + s + ", ");
                }
                else
                {
                    Console.Write("0x0" + s + ", ");
                }
            }
            Console.Write("\r\n");

        }

        void proc(int[] font, String s)
        {
            byte[] str = Encoding.GetEncoding("GB2312").GetBytes(s);

            int tmp1 = str[0] & 0xFF;
            int tmp2 = str[1] & 0xFF;
            if (tmp1 >= 0xA0 && tmp2 >= 0xA0)
            {
                putcgbWin(font, tmp1, tmp2);
            }
        }

        private void button22_Click(object sender, EventArgs e)
        {
            byte[] data = new byte[1024 * 1024];
            //HZK16  0x80000 512k
            {
                FileStream fs = new FileStream("HZK16", FileMode.Open, FileAccess.Read);
                fs.Read(data, 0, (int)fs.Length);
                for (int i = 0; i < fs.Length; i++)
                {
                    byte v = data[0 + i];
                    byte v2 = 0;
                    for (int n = 0; n < 8; n++)
                    {
                        v2 <<= 1;
                        if ((v & 1) != 0)
                        {
                            v2 |= 1;
                        }
                        v >>= 1;
                    }
                    data[0 + i] = v2;
                }
                fs.Close();
            }
            int[] font = new int[1024*1024];
            int index = 0;
            for (int i = 0; i < 1024 * 1024; i+=4) {
                int val = 0;
                val |= data[i];
                val |= data[i + 1] << 8;
                val |= data[i + 2] << 16;
                val |= data[i + 3] << 24;
                font[index++] = val;
            }

            proc(font, "一");
            proc(font, "二");
            proc(font, "三");
            proc(font, "四");
            proc(font, "五");
            proc(font, "六");
            proc(font, "日");

        }

        private void button23_Click(object sender, EventArgs e)
        {
            int bios_pos = 0x072000;
            var shift = bios_pos / 4096;
            write_rom(shift, shift, false);//第二个参数和 verilog 中的 baseAddr = 23'h072000
            
        }

        private void button24_Click(object sender, EventArgs e)
        {

            var shift = 0;//64 * 1024 / 4096;
            write_rom(shift, shift, true);
        }

        private void button25_Click(object sender, EventArgs e)
        {
            int bios_pos = 0x0C4000;//802,570  C3F0A
            var shift = bios_pos / 4096;
            write_rom(shift, shift, false);//第二个参数和 verilog 中的 baseAddr = 23'h072000
        }

        private void button26_Click(object sender, EventArgs e)
        {

            int bios_pos = 0x080000;//7CB88  510856
            var shift = bios_pos / 4096;//
            write_rom(shift, shift, true);
        }

    }
    public class ObjData
    {
        public int vertexesCount;
        public float[] vertexes;//3*n
        public int textureMapCount;
        public float[] textureMap;//2*n
        public int faceCount;
        public int[] faceVerticles;//3*n
        public int[] faceTexture;//3*n
    }
}
